package com.clh.seckill.config;

import com.clh.seckill.pojo.User;
import com.clh.seckill.vo.RespBean;
import com.clh.seckill.vo.RespBeanEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @Author cailinhu
 * @Description TODO
 * @Date 2022/1/21 10:21
 * @Version 1.0
 */
@Aspect
@Component
public class MyAspect {
    @Autowired
    RedisTemplate redisTemplate;

    // 2. PointCut表示这是一个切点，@annotation表示这个切点切到一个注解上，后面带该注解的全类名
    // 切面最主要的就是切点，所有的故事都围绕切点发生
    // logPointCut()代表切点名称
    @Pointcut("@annotation(com.clh.seckill.config.AccessLimit)")
    public void accessPointCut() {
    }
//    @After("accessPointCut()")
//    public void aftereWork(JoinPoint joinPoint){
//        String methodName = joinPoint.getSignature().getName();//方法名称
//
//        // 获取入参
//        Object[] param = joinPoint.getArgs();
//
//        StringBuilder sb = new StringBuilder();
//        for(Object o : param){
//            sb.append(o + "; ");
//        }
//        System.out.println("进入[" + methodName + "]方法,参数为:" + sb.toString());
//
//        System.out.println("aop监听结束！");
//    }

    /**
     * @param joinPoint
     * @param annotation
     * @return
     */
    @Around("accessPointCut()&&@annotation(annotation)")
    public Object aroundAccess(ProceedingJoinPoint joinPoint, AccessLimit annotation) throws Throwable {
        String methodName = joinPoint.getSignature().getName();//方法名称
        HttpServletRequest request = UserContext.getRequest();
        User user = UserContext.getUser();
        //获取注解上的值
        int second = annotation.second();//多少秒失效
        int maxCount = annotation.maxCount();//登录次数
        boolean needLogin = annotation.needLogin();
        String key = request.getRequestURI();
        if (needLogin) {
            if (null == user) {
                //那就不能过了
                return RespBean.error(RespBeanEnum.IDENTITY_OUT, null);
            }
            UserContext.setUser(user);
            key += ":" + user.getId();
        }
        ValueOperations operations = redisTemplate.opsForValue();
        Integer count = (Integer) operations.get(key);
        if (count == null)
            operations.set(key, maxCount, second, TimeUnit.SECONDS);
        else if (count < maxCount)
            operations.increment(key);
        else {
            return RespBean.error(RespBeanEnum.OPERATION_OFTEN, null);
        }
        // 继续执行方法
//            Object proceed() throws Throwable //执行目标方法
//            Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法
            return joinPoint.proceed();
    }
}
